package com.qiongqi.datadir.service.impl;
// PdfViewerServiceImpl.java

import com.qiongqi.datadir.service.IPdfViewerService;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

import static org.apache.commons.lang3.StringUtils.*;

@Service
public class PdfViewerServiceImpl implements IPdfViewerService {

    private static final String ACCESS_PREFIX = "pdf:access:";
    private static final int MAX_ACCESS_COUNT = 5; // 最大访问次数
    private static final long EXPIRE_MINUTES = 10; // Token 有效时间


    private final MinioClient minioClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    public PdfViewerServiceImpl(@Qualifier("minioClient") MinioClient minioClient) {
        this.minioClient = minioClient;
    }

    /**
     * 获取受保护的 PDF 页面图像（带水印）
     * @param bucketName 资源桶名
     * @param objectName 资源对象名
     * @param page 页码（从 1 开始）
     * @param token 访问令牌
     * @param username 用户名
     * @param ip 用户 IP
     * @return 图像字节数组（JPEG）
     */
    @Override
    public byte[] renderSecuredPage(String bucketName, String objectName, int page, String token, String username, String ip)
            throws Exception {
        // MinIO 中的文件 key
        final String fileKey = bucketName + (startsWithIgnoreCase(objectName, "/") ? "" : "/") + objectName;
        // 1. 验证 Token 和访问控制
        if (!validateAccess(token, fileKey, username, ip)) {
            throw new SecurityException("Access denied or expired");
        }

        // 2. 从 MinIO 下载 PDF 流
        InputStream pdfStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());

        try (PDDocument document = PDDocument.load(pdfStream)) {
            if (page < 1 || page > document.getNumberOfPages()) {
                throw new IllegalArgumentException("Invalid page number");
            }

            PDFRenderer renderer = new PDFRenderer(document);
            BufferedImage image = renderer.renderImageWithDPI(page - 1, 150, ImageType.RGB);

            // 3. 添加动态水印
            addDynamicWatermark(image, username, ip, LocalDateTime.now());

            // 4. 输出为 JPEG 字节流
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "jpg", baos);
            return baos.toByteArray();
        }
    }

    private boolean validateAccess(String token, String fileKey, String username, String ip) {
        String key = ACCESS_PREFIX + token;

        String stored = redisTemplate.opsForValue().get(key);
        if (isBlank(stored)) {
            return false;
        }

        // 解析存储的访问信息（可用 JSON，简化为分隔符）
        String[] parts = stored.split("\\|");
        if (ArrayUtils.isNotEmpty(parts) && parts.length != 5) return false;

        String storedFileKey = parts[0];
        String storedUsername = parts[1];
        String storedIp = parts[2];
        long count = Long.parseLong(parts[3]);
        long expireTime = Long.parseLong(parts[4]);

        if (!equalsIgnoreCase(fileKey, storedFileKey) || !equalsIgnoreCase(username,storedUsername)) {
            return false;
        }

        // 检查 IP 一致性（可选）
        // if (!ip.equals(storedIp)) return false;

        if (System.currentTimeMillis() > expireTime) {
            redisTemplate.delete(key);
            return false;
        }

        if (count >= MAX_ACCESS_COUNT) {
            return false;
        }

        // 访问次数 +1
        redisTemplate.opsForValue().set(key, stored.replace("|" + count + "|", "|" + (count + 1) + "|"),
                EXPIRE_MINUTES, TimeUnit.MINUTES);

        return true;
    }

    private void addDynamicWatermark(BufferedImage image, String username, String ip, LocalDateTime time) {
        Graphics2D g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(new Color(255, 255, 255, 100)); // 半透明白
        g.setFont(new Font("SansSerif", Font.BOLD, 20));

        String watermark = String.format("User: %s | IP: %s | Time: %s",
                username, ip, time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        // 动态位置（可多个位置）
        int x = 50;
        int y = image.getHeight() - 50;
        g.drawString(watermark, x, y);

        // 添加对角线水印（可选）
        g.rotate(-Math.PI / 6);
        g.drawString(watermark, image.getWidth() / 2, image.getHeight() / 2);
        g.dispose();
    }

    /**
     * 生成受保护的访问 Token
     * @param bucketName 资源桶名
     * @param objectName 资源对象名
     * @param username 用户名
     * @param ip 用户 IP
     * @return token
     */
    @Override
    public String generateSecureToken(String bucketName, String objectName, String username, String ip) {
        // MinIO 中的文件 key
        final String fileKey = bucketName + (startsWithIgnoreCase(objectName, "/") ? "" : "/") + objectName;
        String raw = fileKey + "|" + username + "|" + ip + "|" + System.currentTimeMillis();
        String token = DigestUtils.md5DigestAsHex(raw.getBytes());

        String value = String.join("|", fileKey, username, ip, "0",
                String.valueOf(System.currentTimeMillis() + EXPIRE_MINUTES * 60 * 1000));

        redisTemplate.opsForValue().set(ACCESS_PREFIX + token, value, EXPIRE_MINUTES, TimeUnit.MINUTES);

        return token;
    }
}